package dongchel.vrp.data;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

import dongchel.vrp.entity.City;
import dongchel.vrp.entity.GlobalInformation;
import dongchel.vrp.entity.PDCity;



public class LoadData {
	private double depotX;
	private double depotY;
	
	public double getDepotX() {
		return depotX;
	}

	public void setDepotX(double depotX) {
		this.depotX = depotX;
	}

	public double getDepotY() {
		return depotY;
	}

	public void setDepotY(double depotY) {
		this.depotY = depotY;
	}

	/**
	 * type 0: general city type 1: pd city
	 * @param path
	 * @param type
	 */
	public void read(String path, int type) {
		

		//File inFile = new File("data/C1_8_5.txt");
		//File inFile = new File("data/C102.txt");
		File inFile = new File(path);

		//File inFile = new File("data/R110.txt");
		//File inFile = new File("data/RC101.txt");
		try {
			BufferedReader fr = new BufferedReader(new FileReader(inFile));
			String nextLine = fr.readLine();

			while (!"".equals(nextLine) && nextLine != null) {
				
				City city = null;
				if(type ==0){
					city = getCity(nextLine);
				}else{
					city = getPDCity(nextLine);
				}
				
				GlobalInformation.cityList.add(city);

				if (GlobalInformation.maxX == -1) {
					GlobalInformation.maxX = city.getX();
					GlobalInformation.minX = city.getX();
					GlobalInformation.maxY = city.getY();
					GlobalInformation.minY = city.getY();
				} else {
					if (city.getX() > GlobalInformation.maxX) {
						GlobalInformation.maxX = city.getX();
					}
					if (city.getX() < GlobalInformation.minX) {
						GlobalInformation.minX = city.getX();
					}
					if (city.getY() > GlobalInformation.maxY) {
						GlobalInformation.maxY = city.getY();
					}
					if (city.getY() < GlobalInformation.minY) {
						GlobalInformation.minY = city.getY();
					}
				}

				nextLine = fr.readLine();
			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		GlobalInformation.cityNum = GlobalInformation.cityList.size();
		
		GlobalInformation.distance = new double[GlobalInformation.cityNum][GlobalInformation.cityNum];
		GlobalInformation.ranks = new int[GlobalInformation.cityNum][GlobalInformation.cityNum];
		calRankInfo();
	}
	
	//calculate rank information
	public void calRankInfo(){		
		
		for(int i=0;i<GlobalInformation.cityNum;i++){
			double[] tempArray = new double[GlobalInformation.cityNum];
			for(int j=0;j<GlobalInformation.cityNum;j++){
				City cityI = GlobalInformation.cityList.get(i);
				City cityJ = GlobalInformation.cityList.get(j);
				double d = 0.0;
				d += Math.pow((cityI.getX()-cityJ.getX()),2)+Math.pow((cityI.getY()-cityJ.getY()),2);
				d = Math.sqrt(d);
				GlobalInformation.distance[i][j] = d;
				tempArray[j] = d;
			}
			int[] resultArray = sortArray(tempArray);
			for(int j=0;j<resultArray.length;j++){
				GlobalInformation.ranks[i][j] = resultArray[j];
			}
		}
	}

	public City getCity(String s) {

		City city = new City();
		if (!"".equals(s) && s != null) {
			Scanner sc = new Scanner(s);
			int id = sc.nextInt();
			
			double x = sc.nextDouble();
			double y = sc.nextDouble();			
			double demand = sc.nextDouble();			
			double etime = sc.nextDouble();			
			double ltime = sc.nextDouble();			
			double serviceTime = sc.nextDouble();
			
			city.setType(0);
			
			city.setId(id);
			city.setX(x);
			city.setY(y);
			city.setDemand(demand);
			city.setEtime(etime);
			city.setLtime(ltime);
			city.setServiceTime(serviceTime);
			
			if(id == 0){
				this.setDepotX(x);
				this.setDepotY(y);
			}else{
				city.setAngle(this.getAngleByXY(x, y));
			}
		}
		return city;
	}
	
	public City getPDCity(String s) {

		City city = new City();
		if (!"".equals(s) && s != null) {
			Scanner sc = new Scanner(s);
			int id = sc.nextInt();
			
			double x = sc.nextDouble();
			double y = sc.nextDouble();			
						
/*			double etime = sc.nextDouble();			
			double ltime = sc.nextDouble();	*/		
	/*		double etime2 = sc.nextDouble();
			double ltime2 = sc.nextDouble();*/
			
			double demand = sc.nextDouble();
			
/*			double serviceTime =sc.nextDouble();*/		
			city.setType(1);					
			city.setId(id);
			city.setX(x);
			city.setY(y);
/*			city.setEtime(etime);
			city.setLtime(ltime);*/
/*			city.setEtime2(etime2);
			city.setLtime2(ltime2);
			city.setServiceTime(serviceTime);*/
			city.setDeliveryDemand(demand);
			if(id%2==0){
				city.setPickupDemand(Math.floor(0.8*demand));
				//city.setPickupDemand(Math.floor(0.2*demand));
			}
			else {
				city.setPickupDemand(Math.floor(1.2*demand));
				//city.setPickupDemand(Math.floor(1.8*demand));
			}
			if(id == 0){
				this.setDepotX(x);
				this.setDepotY(y);
			}else{
				city.setAngle(this.getAngleByXY(x, y));
			}
						
		}
		return city;
	}
	//sort an array
	public int[] sortArray(double[] inputArray){
		int size = inputArray.length;
		List<SortObject> tempList = new LinkedList<SortObject>();
		for(int i=0;i<size;i++){
			SortObject so = new SortObject();
			so.setPosition(i);
			so.setValue(inputArray[i]);
			tempList.add(so);
		}
		Collections.sort(tempList, new MyComparator());
		int[] outputArray = new int[size];
		for(int i=0;i<size;i++){
			SortObject so = tempList.get(i);
			outputArray[i] = so.getPosition();
		}
		return outputArray;
	}
	
	
	//according to x and y value to get angle
	private double getAngleByXY(double x, double y){
		double relativeX = x-this.getDepotX();
		double relativeY = y-this.getDepotY();
		
		double a = Math.atan2(relativeY, relativeX);
				
		return a;
		
	}
	
	public static void main(String[] args){
		LoadData loadData = new LoadData();
		loadData.read("data/pdcity.txt",0);
		for(int i=0;i<GlobalInformation.cityList.size();i++){
			City pdCity =  GlobalInformation.cityList.get(i);
			System.out.println(pdCity.getId()+" "+pdCity.getEtime2()+" "+pdCity.getAngle());
		}
	}
	
}
